/**
 * jQuery fancyzoom plugin. This is an adaptation of the fancyzoom effect as a
 * jQuery plugin
 * 
 * Author: Mathieu Vilaplana <mvilaplana@df-e.com> Date: March 2008 rev 1.0 rev:
 * 1.1 Add title if alt in the img rev 1.2 Correction of the image dimension and
 * close button on top right of the image rev 1.3 now fancyzoom can be apply on
 * an image, no need any more link wrapper rev 1.4 correct the bug for the
 * overlay in ie6 rev 1.6 (09/2009), lot of impovement, now image get out of its
 * context.
 */
(function($) {
	$.fn.fancyzoom = function(userOptions) {
		// the var to the image box div
		var oOverlay = $('<div>').css({
			height : '100%',
			width : '100%',
			position : 'fixed',
			zIndex : 100,
			left : 0,
			top : 0
		});

		function openZoomBox(imgSrc, o) {
			if (o.showoverlay) {
				oOverlay.appendTo('body').click(function() {
					closeZoomBox(o);
				});
				if ($.browser.msie && $.browser.version < 7) {
					oOverlay.css({
						position : 'absolute',
						height : $(document).height(),
						width : $(document).width()
					});
				}
			}
			var oImgZoomBox = o.oImgZoomBox;
			oImgZoomBox.click(function() {
				closeZoomBox(o);
			});
			// calculate the start point of the animation, it start from the
			// image of the element clicked
			pos = imgSrc.offset();
			o = $.extend(o, {
				imgSrc : imgSrc,
				dimOri : {
					width : imgSrc.outerWidth(),
					height : imgSrc.outerHeight(),
					left : pos.left,
					top : pos.top,
					'opacity' : 1
				}
			});
			if (!imgSrc.is('img')) {
				o.dimOri = $.extend(o.dimOri, {
					width : 0,
					height : 0
				});
			}

			oImgZoomBox.css({
				'text-align' : 'center',
				'border' : '0px solid red'
			}).appendTo('body');
			
			// calculate the end point of the animaton
			var iWidth = oImgZoomBox.outerWidth();
			var iHeight = oImgZoomBox.outerHeight();

			// the target is in the center without the extra margin du to close
			// Image
			dimBoxTarget = $.extend({}, {
				width : iWidth,
				height : iHeight,
				'opacity' : 1
			}, __posCenter((iWidth), (iHeight + 30)));

			// place the close button at the right of the zoomed Image
			/*o.oImgClose.css({
				left : (dimBoxTarget.left + dimBoxTarget.width - 15),
				top : (dimBoxTarget.top - 15)
			});*/

			var $fctEnd = function() {
				oImgZoomBox.css("cursor","url("+o.imgDir+"small.cur),auto");
				if($.browser.msie){
					var oImg = oImgZoomBox.find("img");
					oImg.width(oImg.width()-12);
					oImg.height(oImg.height()-12);
				}
				oOverlay.css("cursor","url("+o.imgDir+"small.cur),auto");
			};

			$('div', oImgZoomBox).hide();// cache le titre
			// cache l'image source
			if (o.imgSrc.is('img')) {
				o.imgSrc.css({
					'opacity' : 0
				});
			}
			var oImgDisplay = $('img:first', oImgZoomBox).css({
				'width' : '100%',
				'height' : 'auto'
			});
			if (o.Speed > 0) {
				oImgZoomBox.css(o.dimOri).animate(dimBoxTarget, o.Speed,
						$fctEnd);
			} else {
				oImgZoomBox.css(dimBoxTarget);
				$fctEnd();
			}
			
		}// end openZoomBox

		/**
		 * First hide the closeBtn, then remove the ZoomBox and the overlay
		 * Animate if Speed > 0
		 */
		function closeZoomBox(o) {
			var oImgZoomBox = o.oImgZoomBox;
			//o.oImgClose.remove();
			$('div', oImgZoomBox).remove();
			var endClose = function() {
				oImgZoomBox.empty().remove();
				o.imgSrc.css('opacity', 1);
			};
			if (o.Speed > 0) {
				var pos = oImgZoomBox.offset();
				var iPercent = 0.0;
				var oDimPlus = {
					width : (oImgZoomBox.width() * (1 + iPercent)),
					height : (oImgZoomBox.height() * (1 + iPercent)),
					left : (pos.left - (oImgZoomBox.width() * (iPercent / 2))),
					top : (pos.top - (oImgZoomBox.height() * (iPercent / 2)))
				};
				oImgZoomBox.animate(oDimPlus, o.Speed * 0.02, function() {
					oImgZoomBox.animate(o.dimOri, o.Speed, function() {
						endClose();
					});
					if (o.showoverlay) {
						oOverlay.animate({
							'opacity' : 0
						}, o.Speed, function() {
							$(this).remove();
						});
					}
				});
			} else {
				endClose();
				if (o.showoverlay) {
					oOverlay.remove();
				}
			}
		}

		/**
		 * The plugin chain.
		 */
		return this.each(function() {
			var $this = $(this);
			var imgTarget = $this.is('img') ? $this : ($('img:first',$this).length == 0) ? $this : $('img:first', $this);
			var imgTargetSrc = null;
			if ($this.attr('href')) {
				imgTargetSrc = $this.attr('href');
			}
			/*var oImgClose = $('<img class="jqfancyzoomclosebox">').css(
				{
					position : 'absolute',
					top : 0,
					left : 0,
					cursor : 'pointer'
				}
			);*/

			// build main options before element iteration
			var opts = $.extend(
				{}, 
				$.fn.fancyzoom.defaultsOptions,
				userOptions || {}, {
					dimOri : {},
					oImgZoomBoxProp : {
						position : 'absolute',
						left : 0,
						top : 0
					}//,
					//oImgClose : oImgClose
				}
			);

			if ($this.is('img')) {
				imgTargetSrc = $this.css('cursor', 'pointer').attr('src');
				if (opts.imgResizeScript) {
					if (imgTargetSrc.match(new RegExp("^" + opts.imgResizeScript, "g"))) {
						imgTargetSrc = imgTargetSrc.replace(/.*img=([^&]*).*/gi, '$1');
					}
				}
			}
			oOverlay.css({
				opacity : opts.overlay,
				background : opts.overlayColor
			});

			// make action only on link that point to an image
			/*
			 * if( !/\.jpg|\.jpeg|\.png|\.gif/i.test(imgTargetSrc) ){
			 * return true; }
			 */

			$this.click(function() {
				var zoomOpened = $('div.jqfancyzoombox');
				if (zoomOpened.length > 0) {
					// if user click on an other image, cancel
					// the previous loading
					if ($('img:first', zoomOpened).attr('src') != imgTargetSrc) {
						if (oLoading && oLoading.is(':visible')) {
							__cancelLoading();
						}
					} else {// solve the double click pb
						return false;
					}
				}
				var o = $.extend({}, opts, userOptions);
				
				var closeBtn = $("img.jqfancyzoomclosebox");
				if (closeBtn.length > 0) {
					var imCurrent = $('img:first', zoomOpened);
					if (imgTargetSrc == imCurrent.attr('src')) {
						// calculate the start point of the
						// animation, it start from the image of
						// the element clicked
						pos = imgTarget.offset();
						o = $.extend(o,
								{dimOri : {
												width : (imgTarget
														.outerWidth()),
												height : (imgTarget
														.outerHeight()),
												left : pos.left,
												top : (pos.top),
												'opacity' : 0
									}
								}
						);
						closeZoomBox(o);
						return false;
					} else {
						// user click on an other image, close
						// the first one
						closeBtn.trigger('click');
						// return false;
					}
				}

				// remove the overlay and Reset
				if (o.showoverlay && oOverlay) {
					oOverlay.empty().remove().css({'opacity' : o.overlay});
				}
				// reset the img close and fix png on it if
				// plugin available
				//oImgClose.attr('src', o.imgDir + 'closebox.png').appendTo('body').hide();
				if ($.fn.ifixpng) {
					$.ifixpng(o.imgDir + 'blank.gif');
					//oImgClose.ifixpng(o.imgDir + 'blank.gif');
				}
				//oImgClose.unbind('click').click(function() {
					//closeZoomBox(o);
				//});

				// reset zoom box prop and add image zoom with a
				// margin top of 15px = imgclose height / 2
				var oImgZoomBox = $('<div class="jqfancyzoombox"></div>').css(o.oImgZoomBoxProp);
				o = $.extend(o, {
					oImgZoomBox : oImgZoomBox
				});

				var strTitle = imgTarget.attr('alt');
				if (strTitle){
					var oTitle = $(
							'<div><center><table height=0 border="0" cellspacing=0 cellpadding=0><tr><td></td><td class="fancyTitle">'
									+ strTitle
									+ '</td><td></td></table></center></div>')
							.css({
								marginTop : 10,
								marginRight : 15
							});

					var tdL = oTitle
							.find('td:first')
							.css(
									{
										'background' : 'url('
												+ o.imgDir
												+ 'zoom-caption-l.png)',
										width : '13px',
										height : '26px'
									});
					var tdR = oTitle
							.find('td:last')
							.css(
									{
										'background' : 'url('
												+ o.imgDir
												+ 'zoom-caption-r.png)',
										width : '13px',
										height : '26px'
									});
					var tdC = $('.fancyTitle', oTitle)
							.css(
									{
										'background' : 'url('
												+ o.imgDir
												+ 'zoom-caption-fill.png)',
										'padding' : '0px 20px',
										color : '#FFF',
										'font-size' : '14px'
									});

					if ($.fn.ifixpng) {
						tdL.ifixpng(o.imgDir + 'blank.gif');
						tdR.ifixpng(o.imgDir + 'blank.gif');
						tdC.ifixpng(o.imgDir + 'blank.gif');
					}
					oTitle.appendTo(oImgZoomBox);
				}
				var oImgZoom = $('<img />').attr('src',imgTargetSrc).click(function() {
					closeZoomBox(o);
				}).prependTo(oImgZoomBox);
				
				/** Manage zIndex * */
				var imagezindex = opts.imagezindex;
				oOverlay.css('zIndex', imagezindex - 1);
				oImgZoomBox.css('zIndex', imagezindex);
				//oImgClose.css('zIndex', (imagezindex + 10));
				oImgZoom.css("border","1px solid #ccc");
				oImgZoom.css("background-color","#fff");
				oImgZoom.css("padding","5px");
				
				// be shure that the image to display is loaded
				// open the zoom box, if not display a loading
				// Image.
				var $fctEndLoading = function() {
					if (bCancelLoading) {
						bCancelLoading = false;
					} else {
						if (__getFileName(imgPreload.src) == __getFileName($(
								'img:first', oImgZoomBox).attr(
								'src'))) {
							fctCalculateImageSize(o.autoresize);
							openZoomBox(imgTarget, o);
							__stoploading();
						}
					}
				};
				var fctCalculateImageSize = function(autoresize) {
					// calcul de la taille de l'image
					if (autoresize) {
						var divCalculate = $('<div></div>')
								.css({
									position : 'absolute',
									'top' : 0,
									'left' : 0,
									opacity : 0,
									'border' : '0px solid red'
								});
						var bResize = false;
						oImgZoom.appendTo(divCalculate);
						divCalculate.appendTo('body');
						imWidth = oImgZoom.width();
						imHeight = oImgZoom.height();
						maxWidth = $(window).width() * 0.9;
						maxHeight = $(window).height() - 100;
						if (maxHeight < imHeight) {
							bResize = true;
							oImgZoom.height(maxHeight);
							imWidth = (imWidth * maxHeight) / imHeight;
							oImgZoom.width(imWidth);
							if (maxWidth < imWidth) {
								oImgZoom.width(maxWidth);
								oImgZoom.height(imHeight * maxWidth / imWidth);
							}
						} else if (maxWidth < imWidth) {
							bResize = true;
							oImgZoom.width(maxWidth);
							imHeight = (imHeight * maxWidth) / imWidth;
							oImgZoom.height(imHeight);
							if(maxHeight < imHeight){
								oImgZoom.width(maxHeight);
								oImgZoom.height(imWidth * maxHeight / imWidth);
							}
						}
						// because ie do not resize image
						// correctly
						if (bResize && o.imgResizeScript) {
							var tWidth = oImgZoom.width();
							var tHeight = oImgZoom.height();
							var finalWidth = tWidth;
							var tabSizes = new Array(1440, 1280, 1024, 800, 640, 480, 360);
							for (i = 0; i < tabSizes.length; i++) {
								if (tWidth > tabSizes[i]) {
									finalWidth = tabSizes[i];
									break;
								}
							}
							oImgZoom.width(finalWidth);
							oImgZoom.height(parseInt(tHeight * finalWidth / tWidth));

							var args = "img=" + encodeURI(oImgZoom.attr('src'));
							args += "&width=" + oImgZoom.width();
							args += "&height=" + oImgZoom.height();
							oImgZoom.attr('src', o.imgResizeScript + "?" + args);
						}
						divCalculate.remove();
					}
					oImgZoom.prependTo(oImgZoomBox);
				};

				__displayLoading(o);
				var imgPreload = new Image();
				imgPreload.onload = function() {
					// when loading is finish display the
					// zoombox if user not click on cancel
					$fctEndLoading();
				};
				imgPreload.src = imgTargetSrc;
				
				return false;
			}
			);
		});// end return this
	};// end Plugin

	// Default Options
	$.fn.fancyzoom.defaultsOptions = {
		overlayColor : '#000',
		overlay : 0.6,
		imagezindex : 100,
		showoverlay : true,
		Speed : 200,
		shadow : true,
		shadowOpts : {
			color : "#000",
			offset : 4,
			opacity : 0.2
		},
		imgDir : 'js/fancyzoom/ressources/',
		imgResizeScript : null,
		autoresize : true
	};

	function __posCenter(iWidth, iHeight) {
		var iLeft = ($(window).width() - iWidth) / 2 + $(window).scrollLeft();
		var iTop = ($(window).height() - iHeight) / 2 + $(window).scrollTop();
		iLeft = (iLeft < 0) ? 0 : iLeft;
		iTop = (iTop < 0) ? 0 : iTop;
		return {
			left : iLeft,
			top : iTop
		};
	}

	//
	// LOADING MANAGEMENT
	//
	var oLoading = null;
	var bCancelLoading = false;
	var timerLoadingImg = null;
	function __displayLoading(o) {
		if (!oLoading) {
			oLoading = $('<div></div>').css({
				width : 50,
				height : 50,
				position : 'absolute',
				'background' : 'transparent',
				opacity : 8 / 10,
				color : '#FFF',
				padding : '5px',
				'font-size' : '10px'
			});
		}
		oLoading.css(__posCenter(50, 50)).html(
				'<img src="' + o.imgDir + 'blank.gif" />').click(function() {
			__cancelLoading();
		}).appendTo('body').show();
		timerLoadingImg = setTimeout(function() {
			__changeimageLoading(o);
		}, 400);
	}
	function __cancelLoading() {
		bCancelLoading = true;
		__stoploading();
	}
	function __stoploading() {
		oLoading.hide().remove();
		if (timerLoadingImg) {
			clearTimeout(timerLoadingImg);
			timerLoadingImg = null;
		}
	}

	/**
	 * Animate the png loading image.
	 */
	function __changeimageLoading(o) {
		if (oLoading && !oLoading.is(':visible')) {
			timerLoadingImg = null;
			return;
		}

		var $im = $('img', oLoading);
		// First call im.src ="", set it to the fire png zoom spin
		if (!$im.attr('src') || /blank\.gif/.test($im.attr('src'))) {
			strImgSrc = o.imgDir + "zoom-spin-1.png";
		}
		// rotate the im src until 12
		else {
			tab = $im.attr('src').split(/[- .]+/);
			iImg = parseInt(tab[2]);
			iImg = (iImg < 12) ? (iImg + 1) : 1;
			strImgSrc = tab[0] + "-" + tab[1] + "-" + iImg + "." + tab[3];
		}
		var pLoad = new Image();
		pLoad.src = strImgSrc;
		var $fct = function() {

			oLoading && oLoading.css(__posCenter(50, 50));
			$im.attr('src', strImgSrc);
			timerLoadingImg = setTimeout(__changeimageLoading, 100);
		};
		// to preserve bug if img not exist change it only if load complete.
		if (pLoad.complete) {
			$fct();
		} else {
			pLoad.onload = $fct;
		}
	}

	function __getFileName(strPath) {
		if (!strPath) {
			return false;
		}
		var tabPath = strPath.split('/');
		return ((tabPath.length < 1) ? strPath : tabPath[(tabPath.length - 1)]);
	}

})(jQuery);